package com.nanohadoop.hdfs.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;

/**
 * FileUtils 提供了 HDFS 文件操作相关的工具方法
 */
public class FileUtils {
    private static final Logger log = LoggerFactory.getLogger(FileUtils.class);
    private static final int BUFFER_SIZE = 4096;

    /**
     * 将文件拆分成指定大小的数据块
     *
     * @param file 要拆分的文件
     * @param blockSize 数据块大小(字节)
     * @return 数据块文件列表
     */
    public static List<File> splitFile(File file, long blockSize) throws IOException {
        List<File> blocks = new ArrayList<>();
        
        try (FileInputStream fis = new FileInputStream(file);
             BufferedInputStream bis = new BufferedInputStream(fis)) {
            
            int blockId = 0;
            long remainingBytes = file.length();
            
            while (remainingBytes > 0) {
                int bytesToRead = (int)Math.min(blockSize, remainingBytes);
                byte[] blockBuffer = new byte[bytesToRead];
                int bytesRead = bis.read(blockBuffer);
                
                if (bytesRead > 0) {
                    File blockFile = new File(file.getParent(), 
                        file.getName() + ".block." + blockId);
                    try (FileOutputStream fos = new FileOutputStream(blockFile)) {
                        fos.write(blockBuffer, 0, bytesRead);
                    }
                    blocks.add(blockFile);
                    remainingBytes -= bytesRead;
                    blockId++;
                }
            }
        }
        return blocks;
    }

    /**
     * 合并多个数据块文件成一个完整文件
     *
     * @param blocks 数据块文件列表
     * @param outputFile 输出文件
     */
    public static void mergeBlocks(List<File> blocks, File outputFile) throws IOException {
        try (FileOutputStream fos = new FileOutputStream(outputFile);
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            
            byte[] buffer = new byte[BUFFER_SIZE];
            for (File block : blocks) {
                try (FileInputStream fis = new FileInputStream(block)) {
                    int bytesRead;
                    while ((bytesRead = fis.read(buffer)) > 0) {
                        bos.write(buffer, 0, bytesRead);
                    }
                }
            }
        }
    }

    /**
     * 计算文件的校验和
     */
    public static String calculateChecksum(File file) throws IOException {
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[BUFFER_SIZE];
            java.security.MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
            int bytesRead;
            
            while ((bytesRead = fis.read(buffer)) > 0) {
                digest.update(buffer, 0, bytesRead);
            }
            
            byte[] md5sum = digest.digest();
            StringBuilder result = new StringBuilder();
            for (byte b : md5sum) {
                result.append(String.format("%02x", b));
            }
            return result.toString();
        } catch (Exception e) {
            throw new IOException("计算校验和失败", e);
        }
    }

    /**
     * 创建目录(如果不存在)
     */
    public static void createDirectoryIfNotExists(String path) throws IOException {
        Path dirPath = Paths.get(path);
        if (!Files.exists(dirPath)) {
            Files.createDirectories(dirPath);
        }
    }

    /**
     * 删除文件或目录
     */
    public static void deleteFileOrDirectory(File file) throws IOException {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File f : files) {
                    deleteFileOrDirectory(f);
                }
            }
        }
        if (!file.delete()) {
            throw new IOException("无法删除文件: " + file);
        }
    }

    /**
     * 复制文件
     */
    public static void copyFile(File sourceFile, File destFile) throws IOException {
        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(destFile)) {
            byte[] buffer = new byte[BUFFER_SIZE];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }
        }
    }

    /**
     * 读取文件内容到字节数组
     */
    public static byte[] readFile(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        return Files.readAllBytes(path);
    }

    /**
     * 写入字节数组到文件
     */
    public static void writeFile(String filePath, byte[] data) throws IOException {
        Path path = Paths.get(filePath);
        Files.write(path, data);
    }

    /**
     * 读取文本文件内容
     */
    public static String readFileToString(File file) throws IOException {
        return new String(readFile(file.getPath()), StandardCharsets.UTF_8);
    }

    /**
     * 写入字符串到文本文件
     */
    public static void writeStringToFile(File file, String content) throws IOException {
        writeFile(file.getPath(), content.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 读取文本文件内容到行列表
     */
    public static List<String> readFileToList(File file) throws IOException {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        }
        return lines;
    }
}